// Magic Software, Inc.
// http://www.magic-software.com
// Copyright (c) 2000, All Rights Reserved
//
// Source code from Magic Software is supplied under the terms of a license
// agreement and may not be copied or disclosed except in accordance with the
// terms of that agreement.  The various license agreements may be found at
// the Magic Software web site.  This file is subject to the license
//
// RESTRICTED USE SOURCE CODE
// http://www.magic-software.com/License/restricted.pdf

#ifndef MGCSPATIAL_H
#define MGCSPATIAL_H

#include "MgcBound.h"
#include "MgcMatrix3.h"
#include "MgcObject.h"
#include "MgcRenderState.h"
class MgcNode;


class MgcSpatial : public MgcObject
{
    MgcDeclareRTTI;
    MgcDeclareStream;

public:
    // local transform access
    MgcMatrix3& Rotate ();
    const MgcMatrix3& Rotate () const;
    MgcVector3& Translate ();
    const MgcVector3& Translate () const;
    MgcReal& Scale ();
    const MgcReal& Scale () const;

    // world transform access ('set' should be used only by controllers)
    MgcMatrix3& WorldRotate ();
    const MgcMatrix3& WorldRotate () const;
    MgcVector3& WorldTranslate ();
    const MgcVector3& WorldTranslate () const;
    MgcReal& WorldScale ();
    const MgcReal& WorldScale () const;
    void SetWorldTransformToIdentity ();

    // world bound access
    MgcBound& WorldBound ();
    const MgcBound& WorldBound () const;

    // culling
    bool& ForceCull ();
    const bool& ForceCull () const;

    // render state
    MgcRenderStatePtr SetRenderState (MgcRenderState* pkState);
    MgcRenderState* GetRenderState (MgcRenderState::Type eType);
    MgcRenderStatePtr RemoveRenderState (MgcRenderState::Type eType);
    void RemoveAllStates ();

    // updates (GS = geometric state, RS = renderer state)
    void UpdateGS (MgcReal fAppTime, bool bInitiator = true);
    void UpdateRS (MgcRenderState* apkPreviousState[] = 0);

    // parent access
    MgcNode* GetParent ();

protected:
    // allow internal calls to updates and drawing
    friend class MgcBspNode;
    friend class MgcConvexRegionManager;
    friend class MgcNode;
    friend class MgcRenderer;
    friend class MgcSwitchNode;

    // construction (abstract base class)
    MgcSpatial ();
    virtual ~MgcSpatial ();

    // parent access
    void SetParent (MgcNode* pkParent);

    // geometric updates
    virtual void UpdateWorldData (MgcReal fAppTime);
    virtual void UpdateWorldBound () = 0;
    void PropagateBoundToRoot ();

    // render state updates
    virtual void UpdateRenderState (MgcRenderState* apkState[]) = 0;
    void PropagateStateFromRoot (MgcRenderState* apkState[]);

    // drawing
    void OnDraw (MgcRenderer& rkRenderer);
    virtual void Draw (MgcRenderer& rkRenderer) = 0;


    // parents
    MgcNode* m_pkParent;

    // local transforms
    MgcMatrix3 m_kRotate;
    MgcVector3 m_kTranslate;
    MgcReal m_fScale;

    // world transforms
    MgcMatrix3 m_kWorldRotate;
    MgcVector3 m_kWorldTranslate;
    MgcReal m_fWorldScale;

    // world bound
    MgcBound m_kWorldBound;

    // culling
    bool m_bForceCull;

    // render state
    MgcRenderState::List* m_pkStateList;
};

MgcSmartPointer(MgcSpatial);
MgcRegisterStream(MgcSpatial);
#include "MgcSpatial.inl"

#endif
